#include "serversetting.h"
#include <QDebug>
#include <QNetworkInterface>
#include <QFile>
#include <QStringList>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include "module/const_define.h"

//reversal
void Rev_128Bit(unsigned char * ca)
{
    int index = 0;

    for(index=0;index < 16;index++)
    {
        ca[index] = ~ca[index];
    }
}

//a > b ,ignore MSB carry bit
void Sub_128Bit(unsigned char * sa, unsigned char * sb, unsigned char * sc)
{
    int index = 0;
    int temp = 0,lend = 0;

    // from low bit to hight
    for(index=15;index >= 0; index--)
    {
        temp = sa[index] - sb[index] - lend;

        if(temp < 0)
        {            
            temp = 256 + sa[index] - sb[index] - lend;
            lend = 1;
        }
        else
        {
            lend = 0;
        }

        sc[index] = (unsigned char)temp;

    }
}

char hexCharToValue(char ch)
{
  char result = 0;

  //number
  if((ch >= 0x30) && (ch <= 0x39))
  {
    result = ch;
  }
  //lower
  else if((ch >= 0x61) && (ch <= 0x7a))
  {
    result = (char)(ch - 0x20);
  }
  //upper
  else if((ch >= 0x41) && (ch <= 0x5A))
  {
    result = ch;
  }
  else
  {
    result = '?';
  }

  return result;
}

/////////////////////////////////////////////////////////////////
/// \brief signle
///
static ServerSetting *signle = NULL;

ServerSetting * ServerSetting::defaultSetting()
{    
    if(signle == NULL)
        signle = new ServerSetting();
    return signle;
}

void ServerSetting::clearDefaultSetting()
{
    if(signle != NULL)
    {
        delete signle;
        signle = NULL;
    }
}

#define DEV_PATH "/sys/class/leds/wdt_sp706_wdi/brightness"

unsigned char 	togLedStat(void)
{
    int backlight_fd;
    int bytes;
    int ret;
    char brightness[16] = {0};
    unsigned char statled;

    backlight_fd = open(DEV_PATH, O_RDWR);
    ret = read(backlight_fd, brightness, 1);

    switch(brightness[0])
    {
        case '0':
            statled = 0;
            bytes = sprintf(brightness, "%s\n", "1");
            write(backlight_fd, brightness, bytes);
            break;

        case '1':

            statled = 1;
            bytes = sprintf(brightness, "%s\n", "0");
            write(backlight_fd, brightness, 1);
            break;
        default:
            break;
    }

    close(backlight_fd);
    return statled;
}

ServerSetting::ServerSetting(QObject *parent) :
    QSettings(parent)
{
    path = QString("config.ini");

    doDog();
    connect(&_dogTimer,SIGNAL(timeout()),this,SLOT(doDog()));
    _dogTimer.start(25*1000);

    readConfig();

    _system_ver = 1;
}

void ServerSetting::doDog()
{
    qDebug()<< "Feed the watch dog...";
    _dog.feedTheDog();
}

bool ServerSetting::doStopDog()
{
    qDebug() << "Watch Dog: stop!!";
    _dogTimer.stop();
    return _dog._init_ok;
}

QByteArray ServerSetting::descrySerial()
{
    QString enfile = "/usr/TTG_NETWORK/.TTG_SN";
    //QString enfile = "./.TTG_SN";

    QFile file(enfile);
    QByteArray enData;
    if(file.open(QFile::ReadOnly))
    {
        enData = file.read(512);
        file.close();
    }

    unsigned int length = enData.size();
    unsigned int index = 0x80,offset = 0 ;
    char ch;
    QByteArray deData;

    if(index<length)
    {
        ch = enData.at(index);
        offset = (unsigned int)ch;
        index += offset;
    }

    for(int i=0;i<16;i++)
    {
        if(index < length)
        {
            deData.append(enData.at(index));
            index++;
        }
        else
            break;

        if(index < length)
        {
            ch = enData.at(index);
            index += (unsigned int)ch;
        }
        else
            break;
    }

    return deData;
}

bool ServerSetting::keyAndVerify(QByteArray key)
{
    int fd;

    unsigned char dm2016_value=0;

    if(key.size()!=16)
    {
        qDebug() << "keyAndVerify: size not correct!";
        return false;
    }

    if ((fd = open("/dev/dm2016", O_RDWR)) < 0) {
        qDebug() << "/dev/dm2016 is error";
        return false;
    }

    write(fd,key.data(),16);
    read(fd,&dm2016_value,1);      // 只有读出来为 9 验证成功

    qDebug() << "the return value is " << dm2016_value;

    if(dm2016_value == 9)
        return true;
    else
        return false;

}

QByteArray ServerSetting::readMacData()
{
    QFile file("/usr/TTG_NETWORK/.mac");
    //QFile file("./.mac");

    QByteArray enData;
    if(file.open(QFile::ReadOnly))
    {
        enData = file.read(6);
        file.close();
    }

    return enData;
}

QString ServerSetting::getSerial()
{
    QString serialStr;
    QByteArray seriData = descrySerial();
    if(keyAndVerify(seriData))
    {
        char *pdata = seriData.data();
        unsigned char subData[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
        unsigned char sretData[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
        unsigned char macData[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

        Sub_128Bit((unsigned char*)pdata,subData,sretData);
        Rev_128Bit(sretData);

        QByteArray macFileData = readMacData();

        if(macFileData.size() == 6)
        {
            macData[15] = macFileData.at(5);
            macData[14] = macFileData.at(4);
            macData[13] = macFileData.at(3);
            macData[12] = macFileData.at(2);
            macData[11] = macFileData.at(1);
            macData[10] = macFileData.at(0);

            Sub_128Bit(sretData,macData,sretData);

            for(int i=0;i<8;i++)
            {
                serialStr += hexCharToValue(sretData[i]);
            }

            for(int i=8;i<16;i++)
            {
                 QString number = QString::number(sretData[i],16).toUpper();
                 if(number.size()<2)
                    serialStr += "0" + number;
                 else
                    serialStr += number;
            }

            qDebug() << "Serial:" << serialStr;

        }
        else
        {
            qDebug() << "Serial not found!";
        }

    }

    return serialStr;
}

void ServerSetting::srcAddress2int(QString src)
{
    QStringList l = src.split(".");
    if(l.size() == 3)
    {
        unsigned int a = (l.at(0).toUInt() << 12)& 0xf000;
        unsigned int b = (l.at(1).toUInt() << 8) & 0xf00;
        unsigned int c = l.at(2).toUInt() & 0xff;
        _src_addr = a|b|c;

        qDebug() << "srcAddress2int:" << src << " -> " << _src_addr;
    }
}

void ServerSetting::readConfig()
{
    _serial = getSerial();

    if(!QFile::exists(path))
    {
        writeConfig();
        return ;
    }

//    QFile file(path);
//    if(file.open(QFile::ReadWrite))
//    {
//        qDebug() << "file current path: " << file.fileName();
//    }

    QSettings *configIniRead = new QSettings(path, QSettings::IniFormat);
    //将读取到的ini文件保存在QString中，先取值，然后通过toString()函数转换成QString类型
    //qDebug() <<  configIniRead->childGroups() ;


#ifdef WINDOWS_OS
    qDebug() << "ServerSetting: serial not matter at WIN32!";
    _serial = configIniRead->value("serial").toString();
    keyVerifyOK = true;
#else

    if(_serial.isEmpty())
    {
        qDebug() << "ServerSetting: serial not found!";
        keyVerifyOK = false;
    }
    else
    {
        keyVerifyOK = true;
    }

#endif

    _cloundServerIp = configIniRead->value("server_ip").toString();
    _user = configIniRead->value("user").toString();
    _password = configIniRead->value("password").toString();
    _ip = configIniRead->value("ip").toString();
    _port = configIniRead->value("port").toString();
    _aeskey = configIniRead->value("key").toString();
    _network = configIniRead->value("network").toString();
    _project_url = configIniRead->value("project_url").toString();
    _update_url = configIniRead->value("update_url").toString();
    _rstate_url = configIniRead->value("rstate_url").toString();
    _record_url = configIniRead->value("record_url").toString();
    _reload_knx= configIniRead->value("reload_knx").toString();
    _ip_update = configIniRead->value("ip_update").toString();
    _push_ip = configIniRead->value("server_push").toString();
    _push_serial = configIniRead->value("serial_push").toString();

    QString s_src_addr = configIniRead->value("src_addr").toString();
    _record = configIniRead->value("record").toUInt();

    if(!_project_url.isEmpty() && !_project_url.startsWith("http"))
        _project_url = "http://" +_cloundServerIp + _project_url;

    if(!_update_url.isEmpty() && !_update_url.startsWith("http"))
        _update_url = "http://" + _cloundServerIp + _update_url;

    if(!_rstate_url.isEmpty() && !_rstate_url.startsWith("http"))
        _rstate_url = "http://" +_cloundServerIp + _rstate_url;

    if(!_record_url.isEmpty() && !_record_url.startsWith("http"))
        _record_url = "http://" + _cloundServerIp + _record_url;

    if(_ip_update.isEmpty())
        _ip_update = "120.76.205.173";

    if(_reload_knx.isEmpty())
        _reload_knx="1";

    if(s_src_addr.isEmpty())
        s_src_addr = "15.14.100";

    srcAddress2int(s_src_addr);

    qDebug() << "ServerSetting readConfig: "<< _cloundServerIp << _serial;

    //读入入完成后删除指针
    delete configIniRead;
}

void ServerSetting::writeConfig()
{
    QSettings *configIniWrite = new QSettings(path, QSettings::IniFormat);
   //向ini文件中写入内容,setValue函数的两个参数是键值对

   //向ini文件的第一个节写入内容,Server节下的第一个参数
   configIniWrite->setValue("server_ip", _cloundServerIp);
   //向ini文件的第一个节写入内容,ip节下的第二个参数
   configIniWrite->setValue("serial", _serial);
   configIniWrite->setValue("network", _network);
   configIniWrite->setValue("ip", _ip);
   configIniWrite->setValue("port", _port);
   configIniWrite->setValue("user", _user);
   configIniWrite->setValue("password", _password);
   configIniWrite->setValue("key", _aeskey);
   configIniWrite->setValue("project_url", _project_url);
   configIniWrite->setValue("update_url", _update_url);
   configIniWrite->setValue("reload_knx", _reload_knx);
    //写入完成后删除指针
   delete configIniWrite;
}

QString ServerSetting::getAesKey()
{
    return QString("TTG-hinwo-%1").arg(this->_aeskey);
}

QString ServerSetting::getHostIpString(QString ethName)
{
    QList<QNetworkInterface> lists = QNetworkInterface::allInterfaces();
    QString foundIp;
    foreach (QNetworkInterface it, lists) {
        qDebug() << "QNetworkInterface loop , name:" << it.name() ;
        if(it.name().startsWith(ethName))
        {
            QList<QNetworkAddressEntry> entryList =it.addressEntries();
                  //获取IP地址条目列表，每个条目中包含一个IP地址，一个子网掩码和一个广播地址
             foreach(QNetworkAddressEntry entry,entryList)
             {//遍历每一个IP地址条目
                   qDebug()<<"IP Address: "<<entry.ip().toString();
//                 //IP地址
//                 qDebug()<<"Netmask: "<<entry.netmask().toString();
//                 //子网掩码
//                 qDebug()<<"Broadcast: "<<entry.broadcast().toString();
//                 //广播地址
                 QString dotIp = entry.ip().toString();
                 if(dotIp.contains(QChar('.')) && !dotIp.startsWith("127") && !dotIp.startsWith("0") && !dotIp.startsWith("254"))
                 {
                     //qDebug() << QString("get %1 NetWork ip address %2").arg(ethName).arg(dotIp);
                     foundIp = dotIp ;
                 }
                 else
                     continue;
             }
        }
    }

    return foundIp;
}
